home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / modules / nessus-2.2.8.mo / usr / lib / nessus / plugins / http_keepalive.inc < prev    next >
Text File  |  2005-03-31  |  10KB  |  387 lines

  1. # -*- Fundamental -*-
  2. # http_keepalive.inc
  3. # (C) Renaud Deraison
  4. # $Id: http_keepalive.inc,v 1.46 2005/02/19 17:08:36 renaud Exp $
  5. #
  6. #
  7. # The only function which should be used by an external plugin is
  8. # http_keepalive_send_recv(port, data) which returns the result
  9. # (or NULL if no connection could be established).
  10. #
  11. # Note that the file "http_func.inc" must also be included when
  12. # using this file.
  13. #
  14.  
  15. global_var __ka_socket, __ka_port, __ka_enabled, __ka_last_request;
  16.  
  17. __ka_socket = 0;
  18. __ka_port   = 0;
  19. __ka_enabled = -1;
  20. __ka_last_request = "";
  21.  
  22.  
  23. #if (isnull(debug_level)) include("global_settings.inc");
  24.  
  25. #
  26. # Based on the last headers we received, we determine if we need
  27. # to close our socket and re-open it or not
  28. #
  29. function http_keepalive_check_connection(headers)
  30. {
  31.  tmp = egrep(pattern:"^Connection: [Cc]lose", string:headers);
  32.  if(tmp)
  33.  {
  34.      http_close_socket(__ka_socket);
  35.      __ka_socket = http_open_socket(__ka_port);
  36.  }
  37. }
  38.  
  39. function enable_keepalive(port)
  40. {
  41.  __ka_enabled = 1;
  42.  __ka_port    = port;
  43.  __ka_socket  = http_open_socket(port);
  44. }
  45. #
  46. # This function determines if the remote web server is
  47. # keep-alive-enabled or not.
  48. #
  49. function http_keepalive_enabled(port)
  50. {
  51.   local_var req, soc, r, kb;
  52.   
  53.   kb = get_kb_item(strcat("www/", port, "/keepalive"));
  54.  
  55.   if(kb == "yes"){
  56.       enable_keepalive(port:port);
  57.     return(1);
  58.     }
  59.   else if(kb == "no")return(0);
  60.  
  61.   req = strcat('GET / HTTP/1.1\r\n',
  62. 'Connection: Keep-Alive\r\n',
  63. 'Host: ', get_host_name(), '\r\n',
  64. 'Pragma: no-cache\r\n',
  65. 'User-Agent: Mozilla/4.75 [en] (X11, U; Nessus)\r\n\r\n');
  66.  
  67.   soc = http_open_socket(port);
  68.   if(!soc)return -2;
  69.   send(socket:soc, data:req);
  70.   r = http_recv(socket:soc);
  71.  
  72.  
  73.   # Apache
  74.   if(egrep(pattern:"^Keep-Alive:.*", string:r))
  75.       {
  76.     http_close_socket(soc);
  77.     set_kb_item(name:strcat('www/', port, '/keepalive'), value:"yes");
  78.     enable_keepalive(port:port);
  79.         return(1);
  80.     }
  81.   else
  82.       {
  83.     # IIS
  84.     send(socket:soc, data:req);
  85.     r = http_recv(socket:soc);
  86.     http_close_socket(soc);
  87.     if(strlen(r)){
  88.         set_kb_item(name:strcat("www/", port, "/keepalive"), value:"yes");
  89.         enable_keepalive(port:port);
  90.         return(1);
  91.         }
  92.     }
  93.  
  94.  set_kb_item(name:strcat("www/", port, "/keepalive"), value:"no");
  95.  return(0);
  96. }
  97.  
  98.  
  99. #
  100. # This function is akin to http_recv_body() except that if the last request
  101. # was a HEAD, we bail out (whereas http_recv() will timeout).
  102. #
  103. function http_keepalive_recv_body(headers, bodyonly)
  104. {
  105.   local_var body, length, tmp, chunked, killme;
  106.  
  107.   killme = 0;
  108.   length = -1;
  109.  
  110.   if(ereg(pattern:"^HEAD.*HTTP/.*", string:__ka_last_request))
  111.    {
  112.    # HEAD does not return a body
  113.    http_keepalive_check_connection(headers:headers);
  114.    if(bodyonly) return("");
  115.    else return(headers);
  116.    }
  117.  
  118.  
  119.   if("Content-Length" >< headers)
  120.   {
  121.     tmp = egrep(string:headers, pattern:"^Content-Length: *[0-9]+");
  122.     if ( tmp ) length = int(ereg_replace(string:tmp, pattern:"^Content-Length: *([0-9]*)", replace:"\1"));
  123.   }
  124.  
  125.  
  126.  
  127.  if((length < 0) && (egrep(pattern:"transfer-encoding: chunked", string:headers, icase:TRUE)))
  128.  {
  129.    while(1)
  130.    {
  131.    tmp = recv_line(socket:__ka_socket, length:4096);
  132.    length = hex2dec(xvalue:tmp);
  133.    if(length > 1048576)
  134.        {
  135.        length = 1048576;
  136.     killme = 1;
  137.     }
  138.    body  = strcat(body, recv(socket:__ka_socket, length:length+2, min:length+2));
  139.    if (strlen(body) > 1048576) killme = 1;
  140.  
  141.    if(length == 0 || killme){
  142.        http_keepalive_check_connection(headers:headers);
  143.     # This is expected - don't put this line before the previous
  144.        if(bodyonly) return(body);
  145.     else return(strcat(headers, '\r\n', body));
  146.     }
  147.    }
  148.  }
  149.  
  150.  
  151.  if(length >= 0)
  152.  {
  153.    # Don't receive more than 1 MB
  154.    if (length > 1048576) length = 1048576;
  155.  
  156.    body = recv(socket:__ka_socket, length:length, min:length);
  157.  }
  158.  else {
  159.      # If we don't have the length, we close the connection to make sure
  160.     # the next request won't mix up the replies.
  161.  
  162.      #display("ERROR - Keep Alive, but no length!!!\n", __ka_last_request);
  163.     body = recv(socket:__ka_socket, length:16384);
  164.         if (body =~ '<html>' && body !~ '</html>')    # case insensitive
  165.         {
  166.          repeat
  167.          {
  168.           tmp = recv(socket:__ka_socket, length:16384);
  169.           body += tmp;
  170.          }
  171.          until (! tmp || body =~ "</html>");
  172.          if (debug_level && body !~ "</html>") display("http_keepalive_recv_body: incomplete body?\n------------\n", body, "\n------------\n");
  173.         }
  174.     http_close_socket(__ka_socket);
  175.     __ka_socket = http_open_socket(__ka_port);
  176.     }
  177.  
  178.  
  179.  http_keepalive_check_connection(headers:headers);
  180.  if(bodyonly) return(body);
  181.  else return(strcat(headers, '\r\n', body));
  182. }
  183.  
  184.  
  185. #----------------------------------------------------------------------#
  186.  
  187. # We close our socket on exit.
  188. function on_exit()
  189. {
  190.   if(__ka_socket)
  191.   {
  192.     http_close_socket(__ka_socket);
  193.   }
  194. }
  195.  
  196.  
  197.  
  198. #----------------------------------------------------------------------#
  199.  
  200.  
  201. #
  202. # This is our "public" Keep-Alive function. It sends <data> to the remote
  203. # host on port <port>, and returns the result, or NULL if no connection
  204. # could be established.
  205. #
  206. function http_keepalive_send_recv(port, data, bodyonly)
  207. {
  208.   local_var id, n, ret, headers;
  209.  
  210.   if (debug_level > 1) 
  211.    display("http_keepalive_send_recv(port: ", port, ", data: ", data, ", bodyonly: ", bodyonly, ")\n");
  212.  
  213.   if ( ! data ) { display("http_keepalive_send_recv(): NULL data!\n"); return NULL; }
  214.  
  215.   if(__ka_enabled == -1) __ka_enabled = http_keepalive_enabled(port:port);
  216.   if(__ka_enabled == -2) return NULL;
  217.  
  218.  
  219.   if(__ka_enabled == 0)
  220.   {
  221.     local_var soc, r, body;
  222.     soc = http_open_socket(port);
  223.     if(!soc)return NULL;
  224.     if (send(socket:soc, data:data) <= 0)
  225.     {
  226.       http_close_socket(soc);
  227.       return NULL;
  228.     }
  229.     headers = http_recv_headers(soc);
  230.     if(headers) body = http_recv_body(socket:soc, headers:headers, length:0);
  231.     http_close_socket(soc);
  232.     if(bodyonly) return(body);
  233.     else return(strcat(headers, '\r\n', body));
  234.   }
  235.  
  236.  
  237.   if((port != __ka_port)||(!__ka_socket))
  238.   {
  239.     if(__ka_socket)http_close_socket(__ka_socket);
  240.     __ka_port = port;
  241.     __ka_socket = http_open_socket(port);
  242.     if(!__ka_socket)return NULL;
  243.   }
  244.  
  245.   id = stridx(data, '\r\n\r\n');
  246.   data = str_replace(string:data, find:"Connection: Close", replace:"Connection: Keep-Alive", count:1);
  247.   __ka_last_request = data;
  248.   n = send(socket:__ka_socket, data:data);
  249.   if (n >= strlen(data))
  250.     headers = http_recv_headers(__ka_socket);
  251.   if (! headers)
  252.   {
  253.     http_close_socket(__ka_socket);
  254.     __ka_socket = http_open_socket(__ka_port);
  255.     if(__ka_socket == 0)return NULL;
  256.     if (send(socket:__ka_socket, data:data) < strlen(data))
  257.     {
  258.       http_close_socket(__ka_socket);
  259.       __ka_socket = NULL;
  260.       return NULL;
  261.     }
  262.     headers = http_recv_headers(__ka_socket);
  263.   }
  264.  
  265.   return  http_keepalive_recv_body(headers: headers, bodyonly:bodyonly);
  266. }
  267.  
  268.  
  269.  
  270. #
  271. # Same as check_win_dir_trav(), but with KA support
  272. #
  273. function check_win_dir_trav_ka(port, url, quickcheck)
  274. {
  275.   local_var    soc, req, cod, buf;
  276.   #display("check_win_dir_trav(port=", port, ", url=", url, ", quickcheck=", quickcheck, ")\n");
  277.  
  278.  
  279.   req = http_get(item:url, port:port);
  280.   buf = http_keepalive_send_recv(port:port, data:req);
  281.  
  282. #  if (quickcheck)
  283. #  {
  284. #    if (ereg(pattern:"^HTTP/.* 200 ", string:buf)) return (1);
  285. #    return (0);
  286. #  }
  287.  
  288.   if ( ("ECHO" >< buf)          || ("RESET" >!< buf && ("SET " >< buf))  ||
  289.        ("export" >< buf)        || ("EXPORT" >< buf)           ||
  290.        ("doskey" >< buf)        || ("DOSKEY" >< buf)           ||
  291.        ("[boot loader]" >< buf) || ("[fonts]" >< buf)          ||
  292.        ("[extensions]" >< buf)  || ("[mci extensions]" >< buf) ||
  293.        ("[files]" >< buf)       || ("[Mail]" >< buf)           ||
  294.        ("[operating systems]" >< buf)              )
  295.   {
  296.     return(1);
  297.   }
  298.   return(0);
  299. }
  300.  
  301. #
  302. #
  303. #
  304. function is_cgi_installed_ka(item, port)
  305. {
  306.  local_var r, no404, dir, slash, dirs, banner;
  307.  
  308.  
  309.  #
  310.  # Some embedded web servers can not have arbitrary CGIs
  311.  #
  312.  banner = get_http_banner(port:port);
  313.  if ( egrep(pattern:"^Server: (CUPS|MiniServ|AppleShareIP|Embedded HTTPD|IP_SHARER|Ipswitch-IMail|MACOS_Personal_Websharing|NetCache appliance|ZyXEL-RomPager|cisco-IOS|u-Server)", string:banner ) )    
  314.     return NULL;
  315.  
  316.  if(item[0] != "/")
  317.  {
  318.   dirs = cgi_dirs();
  319.   slash = "/";
  320.  }
  321.  else
  322.  {
  323.   dirs = make_list("");
  324.   slash = "";
  325.  }
  326.  
  327.  no404 = get_kb_item(strcat("www/no404/", port));
  328.  
  329.  foreach dir (dirs)
  330.  {
  331.  r = http_keepalive_send_recv(port:port, data:http_get(item:dir + slash + item, port:port));
  332.  if( r == NULL ) return NULL;
  333.  
  334.  if(r =~ "^HTTP/1\.[0-9.] +200 +")
  335.   {
  336.   if(no404 && tolower(no404) >< tolower(r)) return 0;
  337.   if (debug_level > 1) display("is_cgi_installed_ka(item: ", item, ", port:", port, ")\n------------\n", r, "\n------------\n");
  338.   return(1);
  339.   }
  340.  }
  341.  return(0);
  342. }
  343.  
  344. #
  345.   
  346. function get_http_page(port, url, redirect)
  347. {
  348.   local_var    r, u, v, i, l, seen_loc, n;
  349.  
  350.   if (isnull(redirect))
  351.     n = 32;
  352.   else if (redirect <= 0)
  353.     n = 1;
  354.   else
  355.     n = redirect + 1;
  356.  
  357.   seen_loc = make_list();
  358.   u = url;
  359.   for (i = 0; i < n; i ++)    # Limited iterations to avoid traps
  360.   {
  361.     seen_loc[u] = 1;
  362.     r = http_keepalive_send_recv(port: port, 
  363.                 data: http_get(port: port, item: u));
  364.     if (isnull(r)) return NULL;
  365.  
  366.     if (r =~ "^HTTP/1\.[01] +30[0-9] .*")
  367.     {
  368.       v = eregmatch(pattern: "\r\nLocation: *([^ \t\r\n]+)[ \t]*[\r\n]+",
  369.         string: r, icase: 1);
  370.       if (isnull(v)) return NULL;    # Big problem
  371.       l = v[1];
  372.       if (seen_loc[l]) return NULL;
  373.       seen_loc[l] = 1;
  374.     }
  375.     else if (r =~ "^HTTP/1\.[01] +200 ")
  376.     {
  377.       r = strstr(r, '\r\n\r\n');
  378.       r = substr(r, 4);
  379.       return r;
  380.     }
  381.     else    # Code 4xx or 5xx
  382.       return NULL;
  383.   }
  384.   # Loop?
  385.   return NULL;
  386. }
  387.